#pragma once

#include "SDLRenderer.h"
#include "IMouseListener.h"

namespace ZeEngine
{
    class ResourceManager;

    class GUIObject : public IMouseListener
    {
        friend class GUISystem;

    public:
        GUIObject();
        virtual ~GUIObject();

        virtual void Render(SDL_Renderer& renderer) {}
        virtual bool Update() { return false; }
        virtual void Destroy() {}

        //IMouseListener
        virtual bool OnMouseButtonPressed(const Vector2D<s32>& absolute, s32 button) override { return false; }
        virtual bool OnMouseButtonReleased(const Vector2D<s32>& absolute, s32 button) override { return false; }

        //Caused when a button is let go or pressed but is not in focus
        virtual void OnMouseButtonDown(const Vector2D<s32>& absolute, s32 button) {}
        virtual void OnMouseButtonUp(const Vector2D<s32>& absolute, s32 button) {}

        virtual void OnMouseIn() {}
        virtual void OnMouseOver() {}
        virtual void OnMouseOut() {}

        void AddChild(std::shared_ptr<GUIObject>);

        void SetPosition(const Vector2D<float> position);

        const Vector2D<float>& GetAbsolutePosition() const { return m_position + m_offset; }
        const Vector2D<float>& GetRelativePosition() const { return m_position; }
        const Vector2D<float>& GetSize() const { return m_size; }

        u32 GetID() const { return m_id; }
        const SDL_Rect& GetRectangle() const { return m_rect; }

        void Hide() { m_hidden = true;  }
        void Show() { m_hidden = false; }
        bool IsHidden() const  { return m_hidden; }

    public:
        bool operator==(const GUIObject &other) const;
       
    protected:
        void Init(const Vector2D<float>& position, const Vector2D<float>& size);

        template<typename T>
        T* LoadResource(const std::string& path, const std::string& resource)
        {
            T* pResource = NULL;

            if (m_pResourceManager)
            {
                pResource = m_pResourceManager->GetResource<T>(resource, path);
            }

            if (!pResource)
            {
                LOG_ERROR("Error loading resource: " + path + ":" + resource);
            }

            return pResource;
        }

        SDLRenderer& GetRenderer() { return m_renderer; }

    private:

        u32        m_id;
        static u32 m_currentId;

        static ResourceManager* m_pResourceManager;

        SDL_Rect   m_rect;

        Vector2D<float> m_position;
        Vector2D<float> m_size;
        Vector2D<float> m_offset;

        bool            m_hidden;

        SDLRenderer m_renderer;

        std::vector<std::shared_ptr<GUIObject>> m_children;
    };
}

